home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /*
- * pick2.c: an openGL RGB, double buffered and overlay window example
- * program to demonstrate picking in openGL.
- *
- * - LEFTMOUSE: move the polygons around a center
- * - RIGHTMOUSE: use rubber band to pick polygons
- * - Esc key: exit
- *
- * By Philip W. Ho
- */
-
- /* Compile: cc -o pick2 pick2.c -lGL -lGLU -lXext -lX11 */
- /* Usage: pick2 [nx] [ny] */
- /* nx - no. of polygons in x direction
- ny - no. of polygons in y direction */
-
- #include <GL/glx.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <X11/keysym.h>
- #include <X11/Xlib.h>
- #include <X11/Xutil.h>
-
- #define TRUE 1
- #define FALSE 0
-
- Display *dpy; /* The X server connection */
- Atom del_atom; /* WM_DELETE_WINDOW atom */
- Window glwin, o_win=NULL; /* handle to the GL window */
- XEvent event;
- XWindowAttributes winattri;
- unsigned long fore,back;
- XGCValues values;
- GC mygc;
- long valuemask;
-
- GLXContext cx,cx_o;
-
- /* Data for polygon */
- typedef struct {
- int id;
- float xyz[3];
- } Grid;
-
- typedef struct {
- int id;
- int type;
- int nd;
- int conn[4];
- int colr;
- float xyz[12];
- } Elem;
-
-
- int double_buffer = TRUE;
-
- XColor green_pixel,green_exact;
-
- int no_grid;
- int no_elem;
- int nx,ny;
- int picking;
- Elem *elem, *em;
- Grid *grid, *gd;
-
- #define pick_buffer_size 2000
- GLuint pick_buffer[pick_buffer_size];
-
- /* function declarations */
-
- static void openwindow(char *);
- static void resize_buffer(void);
- static void clean_exit(void);
- void initGL(void);
- void orient(void);
- void drawScene(void);
- void drawPolys(void);
- void DrawXorPolyline(int , XPoint *);
- void gendata(int, int);
- void reset_color(void );
- void open_auxwin(void );
- void clearbox(void );
- void set_picking(XPoint *);
-
- static float objmat[16] = {
- 1.0, 0.0, 0.0, 0.0,
- 0.0, 1.0, 0.0, 0.0,
- 0.0, 0.0, 1.0, 0.0,
- 0.0, 0.0, 0.0, 1.0,
- };
-
- int xsize, ysize; /* current size-of-window keepers */
- double scrnaspect; /* aspect ratio value */
- int xpos, ypos, oxpos, oypos; /* old and new mouse position */
- XPoint box[5];
- int xup1,yup1;
- int xup2,yup2;
-
-
- main(argc,argv)
- int argc;
- char **argv;
- {
- int myExpose, myConfigure, myButtPress, myKeyPress;
- int firsttime,myXor;
- int needToDraw = 0; /* don't set this to true until
- we get our first Expose event */
-
- myExpose = myConfigure = myButtPress = myKeyPress = FALSE;
- myXor = FALSE;
- firsttime = 0;
-
- if(argc == 3)
- {
- nx = atoi(argv[1]);
- ny = atoi(argv[2]);
- }
- else
- {
- nx = 10;
- ny = 10;
- }
-
- openwindow(argv[0]);
-
- gendata(nx,ny);
-
- picking = 0;
-
- /* start out making the singlebuffer window be our current GL window */
- initGL(); /* do GL init stuff */
-
- /*
- * The event loop.
- */
- while (1) { /* standard logic: get event(s), process event(s) */
-
- XEvent event;
- KeySym keysym;
- char buf[4];
-
- /* this "do while" loop does the `get events' half of the "get events,
- * process events" action of the infinite while. this is to ensure
- * the event queue is always drained before the events that have come
- * in are processed.
- */
- do {
-
- XNextEvent(dpy, &event);
- switch (event.type) {
-
- /* "Expose" events are sort of like "REDRAW" in gl-speak in
- * terms of when a window becomes visible, or a previously
- * invisible part becomes visible.
- */
- case Expose: /* Exposures */
- needToDraw = myExpose = TRUE;
- if(o_win == NULL)
- open_auxwin();
- break;
-
- case ButtonPress:
- if( event.xbutton.button == Button3)
- {
- xup1 = event.xmotion.x;
- yup1 = event.xmotion.y;
- box[0].x = xup1;
- box[0].y = yup1;
- box[4].x = xup1;
- box[4].y = yup1;
- myXor = TRUE;
- firsttime = TRUE;
- }
- if( event.xbutton.button == Button2)
- {
- reset_color();
- drawScene();
- }
- break;
-
- case ButtonRelease:
- if( event.xbutton.button == Button3)
- {
- int xsz,ysz;
-
- xup2 = event.xmotion.x;
- yup2 = event.xmotion.y;
- box[1].x = xup2;
- box[1].y = yup1;
- box[2].x = xup2;
- box[2].y = yup2;
- box[3].x = xup1;
- myXor = FALSE;
- xsz = abs(xup2-xup1);
- ysz = abs(yup2-yup1);
-
- if( xsz>0 && ysz>0)
- {
- DrawXorPolyline(5,box);
- set_picking(box);
- drawScene();
- }
- clearbox();
- }
- break;
-
- /* "ConfigNotify" events are like "REDRAW" in terms of changes
- * to a window's size or position.
- */
- case ConfigureNotify: /* Resize GL manually */
- xsize = event.xconfigure.width;
- ysize = event.xconfigure.height;
- needToDraw = myConfigure = TRUE;
- break;
-
- /* Wait for "MotionNotify" events so the queue doesn't fill up
- */
- case MotionNotify:
- if(myXor)
- {
- if(!firsttime)
- DrawXorPolyline(5,box);
-
- xup2 = event.xmotion.x;
- yup2 = event.xmotion.y;
- box[1].x = xup2;
- box[1].y = yup1;
- box[2].x = xup2;
- box[2].y = yup2;
- box[3].x = xup1;
- box[3].y = yup2;
- DrawXorPolyline(5,box);
- firsttime = FALSE;
- }
- else
- {
- myButtPress = TRUE;
- xpos = event.xmotion.x;
- ypos = event.xmotion.y;
- }
- break;
-
- /* "ClientMessage" is generated if the WM itself is being
- * gunned down and sends an exit signal to any running prog.
- */
- case ClientMessage:
- if (event.xclient.data.l[0] == del_atom)
- clean_exit();
- break;
-
- /* "KeyPress" events are those that would be generated before
- * whenever queueing up any KEYBD key via qdevice.
- */
- case KeyPress:
- /* save out which unmodified key (i.e. the key was
- * not modified w/something like "Shift", "Ctrl",
- * or "Alt") got pressed for use below.
- */
- XLookupString((XKeyEvent *)&event, buf, 4, &keysym, 0);
- myKeyPress = TRUE;
- break;
-
- } /* end switch (event.type) */
-
-
- } while (XPending(dpy)); /* end "do { } while".
- * XPending() is like qtest()--it only
- * tells you if there're any events
- * presently in the queue. it does not
- * disturb queue's contents in any way.
- */
-
- /* On an "Expose" event, redraw the affected pop'd or de-iconized window
- */
- if (myExpose) {
- resize_buffer();
- myExpose = FALSE; /* reset flag--queue now empty */
- }
-
- /* On a "ConfigureNotify" event, the GL window has either been moved or
- * resized. Respond accordingly and then redraw its contents.
- */
- if (myConfigure) {
- oxpos = xpos;
- oypos = ypos;
- resize_buffer();
- myConfigure = FALSE; /* reset flag--queue now empty */
- }
-
- if (needToDraw) {
- drawScene();
- needToDraw = FALSE;
- }
-
- /* On a keypress of Esc key, exit program.
- */
- if (myKeyPress) {
- if (keysym == XK_Escape)
- clean_exit();
- }
-
- if (myButtPress) {
- orient();
- drawScene();
- myButtPress = FALSE;
- }
- } /* end while(1) */
-
- } /* end main */
-
-
- static int attributeOverlay[] = { GLX_BUFFER_SIZE, 2,
- GLX_LEVEL, 1,
- GLX_GREEN_SIZE, 1,
- None };
-
- void open_auxwin()
- {
- XSetWindowAttributes swa;
- XVisualInfo *vi_o;
- Colormap cmap_o;
- Window root;
- unsigned int width,height,border,depth;
- int xorig,yorig;
- int status;
-
- XGetGeometry(dpy,glwin, &root, &xorig, &yorig, &width, &height, &border,
- &depth);
- vi_o = glXChooseVisual(dpy, DefaultScreen(dpy), attributeOverlay);
- if (vi_o == NULL) {
- printf("Unable to obtain Overlay Buffered VISUAL(????)\n");
- exit(0);
- }
- cmap_o = XCreateColormap(dpy, RootWindow(dpy, vi_o->screen),
- vi_o->visual, AllocNone);
-
- status = XAllocNamedColor(dpy,cmap_o,"green",&green_pixel,&green_exact);
- if(status == 0) {
- printf("could not allocate green pixel\n");
- }
-
- swa.colormap = cmap_o;
- swa.border_pixel = green_pixel.pixel;
- swa.border_pixel = BlackPixel(dpy,DefaultScreen(dpy));
- /* express interest in events */;
- swa.event_mask = StructureNotifyMask | ButtonPressMask | ExposureMask |
- Button1MotionMask | KeyPressMask | ButtonReleaseMask |
- Button3MotionMask;
-
- o_win = XCreateWindow(dpy, glwin, 0, 0, width, height, 0, vi_o->depth,
- InputOutput, vi_o->visual, CWBorderPixel|CWColormap,
- &swa);
- XSetWMColormapWindows(dpy, glwin, &o_win, 1);
-
- XMapWindow(dpy, o_win);
- back = BlackPixel(dpy,DefaultScreen(dpy));
- fore = green_pixel.pixel;
-
- values.background=0;
- values.foreground = fore;
- values.function = GXxor;
- valuemask = GCFunction | GCBackground | GCForeground;
- mygc = XCreateGC(dpy,o_win,valuemask,&values);
-
- }
- static int attributeList[] = { GLX_RGBA,
- GLX_DEPTH_SIZE, 16,
- GLX_DOUBLEBUFFER,
- None };
-
- static int attributeList2[] = { GLX_RGBA,
- GLX_DEPTH_SIZE, 16,
- GLX_DOUBLEBUFFER,
- None };
-
-
- static Bool WaitForNotify(Display *d, XEvent *e, char *arg) {
- return (e->type == MapNotify) && (e->xmap.window == (Window)arg);
- }
-
- XSizeHints Winhints; /* used to fix window size */
-
-
- /* openwindow -
- * establish connection to X server, get screen info, specify the
- * attributes we want the WM to try to provide, and create the GL window
- */
- static void openwindow(char *progname) {
-
- XVisualInfo *vi;
- Colormap cmap;
- XSizeHints Winhints; /* used to fix window size */
- XSetWindowAttributes swa;
- int scrnnum; /* X screen number */
- int xorig, yorig; /* window (upper-left) origin */
- long scrnheight;
-
-
- /* define window initial size */
- xorig = 50; yorig = 40;
- xsize = 600; ysize = 600;
- scrnaspect = xsize / (double) ysize;
-
- /* Connect to the X server and get screen info */
- if ((dpy = XOpenDisplay(NULL)) == NULL) {
- fprintf(stderr, "%s: cannot connect to X server %s\n",
- progname, XDisplayName(NULL));
- exit(1);
- }
-
- scrnnum = DefaultScreen(dpy);
- scrnheight = DisplayHeight(dpy, scrnnum);
-
- /* get an appropriate visual */
- vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList);
- if (vi == NULL) {
- fprintf(stderr, "Unable to obtain visual Doublebuffered visual\n");
- vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList2);
- }
- if (vi == NULL) {
- printf("Unable to obtain Singlebuffered VISUAL(????)\n");
- exit(0);
- }
- /* create a GLX context */
- cx = glXCreateContext(dpy, vi, None, GL_TRUE);
-
- /* create a colormap */
- cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen),
- vi->visual, AllocNone);
-
- /* create a window */
- swa.colormap = cmap;
- swa.border_pixel = 0;
- /* express interest in events */;
- swa.event_mask = StructureNotifyMask | ButtonPressMask | ExposureMask |
- Button1MotionMask | KeyPressMask | ButtonReleaseMask | Button3MotionMask;
- glwin = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
- xorig, yorig, xsize, ysize,
- 0, vi->depth, InputOutput, vi->visual,
- CWBorderPixel|CWColormap|CWEventMask, &swa);
- XMapWindow(dpy, glwin);
-
-
- /* XGetWindowAttributes(dpy,glwin,&winattri); */
- /* XGetWindowAttributes(dpy,o_win,&winattri); */
-
- XIfEvent(dpy, &event, WaitForNotify, (char*)glwin);
-
- /* connect the context to the window */
- glXMakeCurrent(dpy, glwin, cx);
-
- /* printf("Back = %d fore = %d\n",back,fore); */
-
- if (!(glwin)) {
- fprintf(stderr,"%s: couldn't create \"parent\" X window\n",progname);
- exit(1);
- }
-
-
- /* define string that will show up in the window title bar (and icon) */
- XStoreName(dpy, glwin, "Picking using overlay ");
-
- /* specify the values for the Window Size Hints we want to enforce: this
- * window's aspect ratio needs to stay at 1:1, constrain min and max
- * window size, and specify the initial size of the window.
- */
- Winhints.width = xsize; /* specify desired x/y size of window */
- Winhints.height = ysize;
- Winhints.min_width = xorig; /* define min and max */
- Winhints.max_width = scrnheight-1; /* width and height */
- Winhints.min_height = yorig;
- Winhints.max_height = scrnheight-1;
- Winhints.min_aspect.x = xsize; /* keep aspect to a xsize:ysize ratio */
- Winhints.max_aspect.x = xsize;
- Winhints.min_aspect.y = ysize;
- Winhints.max_aspect.y = ysize;
- Winhints.flags = USSize|PMaxSize|PMinSize|PAspect; /* set the */
- XSetNormalHints(dpy, glwin, &Winhints); /* corresponding flags */
-
- /* express interest in WM killing this app */
- if ((del_atom = XInternAtom(dpy, "WM_DELETE_WINDOW", True)) != None)
- XSetWMProtocols(dpy, glwin, &del_atom, 1);
-
- return ;
- }
-
- /* window has been moved or resized so update viewport & CTM stuff.
- */
- static void resize_buffer() {
-
- XSync(dpy, False); /* STILL NEED THIS????? *//* Need before GL reshape */
- scrnaspect = xsize / (double) ysize;
- glViewport(0, 0, xsize-1, ysize-1);
- }
-
-
-
- /* clean up before exiting
- */
- static void clean_exit(void)
- {
- XCloseDisplay(dpy);
- exit(0);
- }
-
-
-
- /* setup all necessary GL initialzation parameters.
- */
- void initGL()
- {
- glEnable(GL_DEPTH_TEST);
- glClearColor(0.0, 0.0, 0.0, 0.0);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
-
- /* gluPerspective(400.0, scrnaspect, 30.0, 1000.0); */
-
- glOrtho(-0.5, 0.5, -0.5, 0.5, -12.0, 12.0);
- glMatrixMode(GL_MODELVIEW);
-
- }
-
-
- void orient()
- {
- float dx, dy;
- glPushMatrix();
-
- dx = xpos-oxpos;
- dy = oypos-ypos;
- glLoadIdentity();
- glRotatef((float) (0.03*(xpos-oxpos)), 1.0, 0.0, 0.0);
- glRotatef((float) (0.03*(oypos-ypos)), 0.0, 1.0, 0.0);
- glMultMatrixf(objmat);
- glGetFloatv(GL_MODELVIEW_MATRIX, objmat);
-
- glPopMatrix();
- }
-
-
- void drawScene()
- {
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- glPushMatrix();
- glMultMatrixf(objmat);
- drawPolys();
- glPopMatrix();
- glFlush ();
- glXSwapBuffers(dpy, glwin);
-
-
- }
- void drawPolys()
- {
- int i,j,k;
- int id,col;
-
- col = 1;
- glColor3f(0.8, 0.8, 0.8);
-
- em = elem;
- for(i=0; i<no_elem; i++,em++)
- {
- if(picking)
- {
- id = i+101;
- glPopName();
- glPushName(id);
- }
- if(em->colr != col)
- {
- col = em->colr;
- if(col == 2)
- glColor3f(1.0, 0.0, 0.0);
- else
- glColor3f(0.8, 0.8, 0.8);
- }
- glBegin(GL_LINE_STRIP);
- glVertex3fv(&em->xyz[0]);
- glVertex3fv(&em->xyz[3]);
- glVertex3fv(&em->xyz[6]);
- glVertex3fv(&em->xyz[9]);
- glVertex3fv(&em->xyz[0]);
- glEnd();
- }
-
- }
- void DrawXorPolyline(int num, XPoint *points)
- {
-
- XDrawLines(dpy, o_win, mygc, points, num, CoordModeOrigin);
- XFlush(dpy);
-
- return;
- }
- /* -------------------------------------------------------------------- */
- void gendata(int nx, int ny)
- {
-
- int i,j,k,count;
- int i1,i2,jj,kk,id;
- float dx,dy;
- float x,y,z;
- float xx,yy;
- int nxny;
- int memsize;
-
- no_grid = (nx+1)*(ny+1);
- no_elem = nx*ny;
-
- memsize = no_elem*sizeof(Elem);
- elem = (Elem *)malloc(memsize);
- memsize = no_grid*sizeof(Grid);
- grid = (Grid *)malloc(memsize);
-
- dx = 0.8/(float)nx;
- dy = 0.8/(float)ny;
-
- /* Generate grids */
-
- count = 0;
-
- z = 0.0;
- gd = grid;
-
- y = -0.4;
- for(j=0; j < ny+1; j++)
- {
- x = -0.40;
- for(i=0; i < nx+1; i++)
- {
- gd->id = count+1;
- gd->xyz[0] = x;
- gd->xyz[1] = y;
- gd->xyz[2] = z;
- count++;
- gd++;
- x += dx;
- }
- y += dy;
- }
-
- /* Generate elements */
-
- count=0;
- em = elem;
- for(j=0; j < ny; j++)
- {
- jj = j*(nx+1);
- for(i=0; i < nx; i++)
- {
- em->id = count+1;
- em->type = 0;
- em->nd = 4;
-
- i1 = jj + i;
- i2 = i1 + 1;
- em->conn[0] = i1;
- em->conn[1] = i2;
- em->conn[2] = i2+(nx+1);
- em->conn[3] = i1+(nx+1);
- em->colr = 1; /* 1 for white color, later on change to
- something elese */
- em++;
- count++;
- }
- }
-
- em = elem;
- for(i=0; i<no_elem; i++,em++)
- {
- xx = yy =0.0;
- for(j=0; j<4; j++)
- {
- id = em->conn[j];
- xx += (grid+id)->xyz[0];
- yy += (grid+id)->xyz[1];
- }
- xx = xx*0.25;
- yy = yy*0.25;
-
- for(j=0,k=0; j<4; j++,k+=3)
- {
- id = em->conn[j];
- x = (grid+id)->xyz[0];
- y = (grid+id)->xyz[1];
- z = (grid+id)->xyz[2];
- dx = (xx -x)*0.3 ;
- dy = (yy -y)*0.3 ;
-
- em->xyz[k] = x + dx;
- em->xyz[k+1] = y + dy;
- em->xyz[k+2] = z;
- }
- }
-
- /* write data out to file */
-
- /*
- printf("GRID data\n");
-
- gd = grid;
- for(i=0 ;i< no_grid; i++)
- {
- printf("%6d %15.4f %15.4f %15.4f\n",
- gd->id, gd->xyz[0], gd->xyz[1], gd->xyz[2]);
- gd++;
- }
- printf("ELEMENT data\n");
- em = elem;
- for(i=0; i<no_elem; i++)
- {
- printf("%6d %6d %6d %6d %6d %6d %6d %6d %6d\n",
- em->id, em->conn[0], em->conn[1], em->conn[2], em->conn[3]);
- em++;
- }
- */
- }
- void reset_color()
- {
- int i,j;
- em = elem;
- for(i=0; i<no_elem; i++,em++)
- em->colr = 1;
- for(i=0; i<16; i++)
- objmat[i] = 0.0;
-
- objmat[0] = 1.0;
- objmat[5] = 1.0;
- objmat[10] = 1.0;
- objmat[15] = 1.0;
-
- values.background=0;
- values.foreground = 0;
- values.function = GXcopy;
- valuemask = GCFunction | GCBackground | GCForeground;
- mygc = XCreateGC(dpy,o_win,valuemask,&values);
-
- XFillRectangle(dpy,o_win,mygc,0,0,xsize,ysize);
-
- values.background=0;
- values.foreground = fore;
- values.function = GXxor;
- valuemask = GCFunction | GCBackground | GCForeground;
- mygc = XCreateGC(dpy,o_win,valuemask,&values);
-
- }
- void set_picking(XPoint *box)
- {
-
- int hits,i,j,items,indx;
- int z1,z2,id;
- float x1,x2,y1,y2;
-
- picking = 1;
- glSelectBuffer(pick_buffer_size, pick_buffer);
- glRenderMode(GL_SELECT);
- glInitNames();
- glLoadName(0);
-
- x1 = (float)box[0].x/xsize - 0.5;
- x2 = (float)box[1].x/xsize - 0.5;
- y1 = (float)(ysize-box[0].y)/ysize - 0.5;
- y2 = (float)(ysize-box[2].y)/ysize - 0.5;
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(x1,x2, y1,y2, -12.0, 12.0);
- glMatrixMode(GL_MODELVIEW);
-
- drawScene();
- picking = 0;
-
- reset_color();
- hits = glRenderMode(GL_RENDER);
- indx = 0;
- for(i=0; i<hits; i++)
- {
- items = pick_buffer[indx++];
- z1 = pick_buffer[indx++];
- z2 = pick_buffer[indx++];
- for(j=0; j<items; j++)
- {
- id = pick_buffer[indx++] - 101;
- (elem+id)->colr = 2;
- }
- }
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(-0.5, 0.5, -0.5, 0.5, -12.0, 12.0);
- glMatrixMode(GL_MODELVIEW);
- drawScene();
-
- }
- void clearbox()
- {
- int i;
- for(i=0; i<5; i++)
- {
- box[i].x = 0;
- box[i].y = 0;
- }
- }
-